package ligne2vie.topos.shared.bo;

/**
 * The class {@link CoordinatesConversion} provides a convenience conversion class for all map coordinates.
 * 
 * @author thuguerre
 * @since 1.0.0
 * @see http://www.csu.edu.au/australia/latlong/dms.html
 */
public class CoordinatesConversion {

	/**
	 * The method {@link #fromLatitude(double)} converts a Degree Decimal latitude coordinate into a Degree Minute
	 * Seconds format.
	 * 
	 * @param decimal
	 *            Degree Decimal latitude coordinate.
	 * @return Corresponding DMS format coordinate.
	 * @throws RuntimeException
	 *             if decimal is not in range of -90 to 90.
	 */
	public static DMSCoordinate fromLatitude(double decimal) {

		if (Math.abs(decimal) > 90) {
			throw new RuntimeException("Decimal latitude must be in the range of -90 to 90.");
		}

		char global = decimal > 0 ? 'N' : 'S';
		return CoordinatesConversion.fromDecimal(global, decimal);
	}

	/**
	 * The method {@link #fromLongitude(double)} converts a Degree Decimal longitude coordinate into a Degree Minute
	 * Seconds format.
	 * 
	 * @param decimal
	 *            Degree Decimal longitude coordinate.
	 * @return Corresponding DMS format coordinate.
	 * @throws RuntimeException
	 *             if decimal is not in range of -180 to 180.
	 */
	public static DMSCoordinate fromLongitude(double decimal) {

		if (Math.abs(decimal) > 180) {
			throw new RuntimeException("Decimal longitude must be in the range of -180 to 180.");
		}

		char global = decimal > 0 ? 'E' : 'O';
		return CoordinatesConversion.fromDecimal(global, decimal);
	}

	/**
	 * The method {@link #fromDecimal(double)} converts a Degree Decimal coordinate into a Degree Minute Seconds format.
	 * It must be specified the global part of Earth (North, South, East, West) it is located in.
	 * 
	 * @param decimal
	 *            Degree Decimal coordinate.
	 * @return Corresponding DMS format coordinate.
	 */
	private static DMSCoordinate fromDecimal(char global, double decimal) {

		double degree = Math.floor(decimal);

		// http://www.csu.edu.au/australia/latlong/dms.html
		double _Mm = (decimal - degree) * 60;

		double minute = Math.floor(_Mm);
		double second = Math.floor((_Mm - minute) * 60);

		return new DMSCoordinate(global, degree, minute, second);
	}
}
